Skip to content

Fix non-const global variables#219

Merged
penelopeysm merged 3 commits intomainfrom
py/globals
Mar 18, 2026
Merged

Fix non-const global variables#219
penelopeysm merged 3 commits intomainfrom
py/globals

Conversation

@penelopeysm
Copy link
Copy Markdown
Member

@penelopeysm penelopeysm commented Mar 18, 2026

Closes #211.

The issue here is that for a function like this

a = 1.0
function f()
    return a + 1.0
end

Libtask would transform the original IR

2 1%1 = Main.a::Any                                                                               │
  │   %2 = (%1 + 1.0)::Any                                                                           │
  └──      return %2

to

2 1 ── %1  = (Libtask.resume_block_is)(_1, 5)::Any                                                   │
  └───       nothing::Any2 ──       goto #5 if not %1                                                                       │
  3 ──       goto #4                                                                                 │
  4 ──       (Libtask.set_ref_at!)(_1, 1, Main.a)::Any                                               │
  └───       goto #5                                                                                 │
  5 ┄─ %7  = (Libtask.get_ref_at)(_1, 1)::Any                                                        │
  │    %8  = (Libtask.get_ref_at)(_1, 3)::Any                                                        │
  │    %9  = (%8)(Main.:+, %7, 1.0)::Any                                                             │
  └─── %10 = (Libtask.not_a_produced)(%9)::Any6 ──       goto #8 if not %10                                                                      │
  7 ──       goto #9                                                                                 │
  8 ──       (Libtask.set_resume_block!)(_1, 5)::Any                                                 │
  └───       return %99 ──       (Libtask.set_ref_at!)(_1, 2, %9)::Any                                                   │
  └───       goto #10                                                                                │
  10 ─       (Libtask.set_resume_block!)(_1, -1)::Any                                                │
  │    %18 = (Libtask.get_ref_at)(_1, 2)::Any                                                        │
  └───       return %18 

The issue is the line (Libtask.set_ref_at!)(_1, 1, Main.a)::Any -- because Main.a is not a const global, it for some reason can't be passed as an argument to a function (the error is thrown here https://github.com/JuliaLang/julia/blob/53a02c0720cdc5d7fc0f35447886dd14bb2491a6/base/compiler/ssair/verify.jl#L58-L62). So this PR fixes it by first assigning it to an SSA ID, and then passing that ID to set_ref_at! instead, which gives us this:

2 1 ── %1  = (Libtask.resume_block_is)(_1, 6)::Any                                                   │
  └───       nothing::Any2 ──       goto #5 if not %1                                                                       │
  3 ──       goto #4                                                                                 │
  4 ── %5  = Main.a::Any                                                                             │
  │          (Libtask.set_ref_at!)(_1, 1, %5)::Any                                                   │
  └───       goto #5                                                                                 │
  5 ┄─ %8  = (Libtask.get_ref_at)(_1, 1)::Any                                                        │
  │    %9  = (Libtask.get_ref_at)(_1, 3)::Any                                                        │
  │    %10 = (%9)(Main.:+, %8, 1.0)::Any                                                             │
  └─── %11 = (Libtask.not_a_produced)(%10)::Any6 ──       goto #8 if not %11                                                                      │
  7 ──       goto #9                                                                                 │
  8 ──       (Libtask.set_resume_block!)(_1, 6)::Any                                                 │
  └───       return %109 ──       (Libtask.set_ref_at!)(_1, 2, %10)::Any                                                  │
  └───       goto #10                                                                                │
  10 ─       (Libtask.set_resume_block!)(_1, -1)::Any                                                │
  │    %19 = (Libtask.get_ref_at)(_1, 2)::Any                                                        │
  └───       return %19

@github-actions
Copy link
Copy Markdown

Libtask.jl documentation for PR #219 is available at:
https://TuringLang.github.io/Libtask.jl/previews/PR219/

@penelopeysm
Copy link
Copy Markdown
Member Author

@Technici4n, would you be interested in reviewing? No pressure! It's just we don't have anybody else who knows the IR stuff 😄.

@Technici4n
Copy link
Copy Markdown
Contributor

Sorry I really don't have the bandwidth atm 😅 But you really overestimate my knowledge of IR :)

@penelopeysm
Copy link
Copy Markdown
Member Author

Haha that's totally fine! I will ship it and take responsibility for any bugs 😄

@penelopeysm penelopeysm merged commit e8f6242 into main Mar 18, 2026
22 checks passed
@penelopeysm penelopeysm deleted the py/globals branch March 18, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unbound GlobalRef not allowed in value position

2 participants